package codebot.elector;

import java.util.ArrayList;

/**
 * This class represents an entity which the Elector will chose or not for a
 * certain action. The Candidate can ultimately also be a Supporter of a bigger
 * Candidate.
 * 
 * @author Teo
 * 
 */
public class Candidate implements ISupporter {

	/**
	 * The name of this Candidate
	 */
	private String mName;

	/**
	 * Private resources this Candidate gathers during its lifetime. These are
	 * resources that the Candidate obtains itself, not from Supporters.
	 */
	private int mPrivateRes;

	/**
	 * The list of direct Supporters this Candidate has
	 */
	private ArrayList<ISupporter> mSupporters;

	/**
	 * Set when {@link Candidate#getSupport()} is called. It caches the best
	 * Supporter this class has.
	 */
	private ISupporter mBestSupporter;

	/**
	 * Parameterless construction
	 */
	public Candidate() {
		this("");
	}

	/**
	 * Birth of a candidate
	 */
	public Candidate(final String name) {
		// when the candidate is born, it obviously has nothing:
		mPrivateRes = 0;

		// also doesn't have Supporters at that time as well :)
		mSupporters = new ArrayList<ISupporter>();

		// gets a name though :)
		mName = name;

		// in the beginning there are no supporters, so, obviously, no best
		// supporter
		mBestSupporter = this;
	}

	/**
	 * Adds some resources to the ones the candidate already has.
	 * 
	 * @param newResources
	 */
	public final void acquireResources(final int newResources) {
		mPrivateRes += newResources;
	}

	/**
	 * Returns the best supporter that has been found when the support was
	 * calculated.
	 * 
	 * @return an ISupporter or this very Candidate if there are no supporters
	 */
	public final ISupporter getExecutor() {
		return (mBestSupporter != null) ? mBestSupporter : this;
	}

	@Override
	public final int getSupport() {
		mBestSupporter = Utils.getBestSupporter(mSupporters);
		return mPrivateRes
				+ ((mBestSupporter != null) ? mBestSupporter.getSupport() : 0);
	}

	/**
	 * Tells this Candidate to register a Supporter.
	 * 
	 * @param supporter
	 */
	public final void registerSupporter(final ISupporter supporter) {
		if (!mSupporters.contains(supporter)) {
			mSupporters.add(supporter);
		}
	}

	/**
	 * Tells this Candidate to not count on a certain supporter anymore.
	 * 
	 * @param supporter
	 *            to be removed
	 * @return false if the Supporter wasn't there in the first place
	 */
	public final boolean removeSupporter(final ISupporter supporter) {
		return mSupporters.remove(supporter);
	}

	@Override
	public final void support(final Candidate candidate) {
		candidate.registerSupporter(this);
	}

	@Override
	public String toString() {
		return mName;
	}

}
